package org.ms.mconf.server.springboot.controller;

import javassist.NotFoundException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.ms.mconf.sdk.model.MetaConfig;
import org.ms.mconf.sdk.model.MetaDataConfig;
import org.ms.mconf.sdk.model.NodeConfig;
import org.ms.mconf.sdk.model.NodeMultiConfig;
import org.ms.mconf.server.springboot.BaseApi;
import org.ms.mconf.server.springboot.filter.LanguageFilter;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

@Controller
public class WebController extends BaseApi {

    @RequestMapping("/")
    public String index(HashMap<String, Object> map) {
        map.put("hello", "欢迎进入HTML页面");
        return "index";
    }

    @RequestMapping("main")
    public String main(HashMap<String, Object> map) {
        return "main";
    }

    @RequestMapping(value = "node-config", method = RequestMethod.GET)
    public String nodeConfig(HttpServletRequest request) {
        Set<NodeConfig> nodeConfigs = super.nodeService().query();
        request.setAttribute("nodes", nodeConfigs);
        return "node-config";
    }

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "node-edit/{operation}", method = RequestMethod.GET)
    public String nodeEdit(@PathVariable("operation") String operation, String node, HttpServletRequest request) {
        Map<String, String> languageMap = (Map<String, String>) request.getAttribute(LanguageFilter.LANGUAGE_KEY);
        request.setAttribute("editTitle", languageMap.get(operation));
        request.setAttribute("operation", operation);

        if (StringUtils.isNotBlank(node)) {
            Set<NodeConfig> nodeConfigs = super.nodeService().query();
            if (CollectionUtils.isNotEmpty(nodeConfigs)) {
                Map<String, NodeConfig> nodeConfigMap = nodeConfigs.stream().collect(Collectors.toMap(NodeConfig::getId, Function.identity()));
                NodeConfig nodeConfig = nodeConfigMap.get(node);
                if (nodeConfig != null) {
                    request.setAttribute("nodeConfig", nodeConfig);
                }
            }
        }

        return "node-edit";
    }

    @ResponseBody
    @RequestMapping(value = "submit-node-edit", method = RequestMethod.POST)
    public Boolean submitNodeEdit(NodeConfig nodeConfig) {
        return super.nodeService().publish(nodeConfig);
    }

    @RequestMapping("env-config")
    public String envConfig(HttpServletRequest request) {
        Set<NodeConfig> nodeConfigs = super.envService().query();
        request.setAttribute("envs", nodeConfigs);
        return "env-config";
    }

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "env-edit/{operation}", method = RequestMethod.GET)
    public String envEdit(@PathVariable("operation") String operation, String env, HttpServletRequest request) {
        Map<String, String> languageMap = (Map<String, String>) request.getAttribute(LanguageFilter.LANGUAGE_KEY);
        request.setAttribute("editTitle", languageMap.get(operation));
        request.setAttribute("operation", operation);

        if (StringUtils.isNotBlank(env)) {
            Set<NodeConfig> envConfigs = super.envService().query();
            if (CollectionUtils.isNotEmpty(envConfigs)) {
                Map<String, NodeConfig> nodeConfigMap = envConfigs.stream().collect(Collectors.toMap(NodeConfig::getId, Function.identity()));
                NodeConfig nodeConfig = nodeConfigMap.get(env);
                if (nodeConfig != null) {
                    request.setAttribute("envConfig", nodeConfig);
                }
            }
        }

        return "env-edit";
    }

    @ResponseBody
    @RequestMapping(value = "submit-env-edit", method = RequestMethod.POST)
    public Boolean submitEnvEdit(NodeConfig nodeConfig) {
        return super.envService().publish(nodeConfig);
    }

    @RequestMapping("acv-config")
    public String acvConfig(HttpServletRequest request) {
        Set<NodeMultiConfig> nodeConfigs = super.acvService().query();
        request.setAttribute("acvs", nodeConfigs);
        return "acv-config";
    }

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "acv-edit/{operation}", method = RequestMethod.GET)
    public String acvEdit(@PathVariable("operation") String operation, String application, String config, String version, HttpServletRequest request) {
        Map<String, String> languageMap = (Map<String, String>) request.getAttribute(LanguageFilter.LANGUAGE_KEY);
        request.setAttribute("editTitle", languageMap.get(operation));
        request.setAttribute("operation", operation);

        if (StringUtils.isNotBlank(application) && StringUtils.isNotBlank(config) && StringUtils.isNotBlank(version)) {
            Set<NodeMultiConfig> acvConfigs = super.acvService().query();
            if (CollectionUtils.isNotEmpty(acvConfigs)) {
                for (NodeMultiConfig nodeMultiConfig : acvConfigs) {
                    if (nodeMultiConfig.getApplication().getId().equals(application) &&
                            nodeMultiConfig.getConfig().getId().equals(config) &&
                            nodeMultiConfig.getVersion().getId().equals(version)) {
                        request.setAttribute("acvConfig", nodeMultiConfig);
                    }
                }
            }
        }

        return "acv-edit";
    }

    @ResponseBody
    @RequestMapping(value = "submit-acv-edit", method = RequestMethod.POST)
    public Boolean submitAcvEdit(NodeMultiConfig nodeMultiConfig) {
        return super.acvService().publish(nodeMultiConfig);
    }

    @RequestMapping("data-config")
    public String dataConfig(HttpServletRequest request) {
        List<MetaDataConfig> metaDataConfigs = super.opsService().search(new MetaConfig(), null);
        request.setAttribute("configs", metaDataConfigs);
        return "data-config";
    }

    @ResponseBody
    @RequestMapping("query-data-config")
    public MetaDataConfig queryDataConfig(MetaConfig metaConfig, String key, HttpServletRequest request) {
        MetaDataConfig metaDataConfig = super.opsService().query(metaConfig, key);
        if (metaDataConfig == null) {
            throw new RuntimeException("The NotFound config data");
        }

        return metaDataConfig;
    }

    @RequestMapping("limiter-configs")
    public String limiterConfigs(HashMap<String, Object> map) {
        return "limiter-configs";
    }

    @RequestMapping("limiter-config")
    public String limiterConfig(HashMap<String, Object> map) {
        return "limiter-config";
    }

    @RequestMapping("limiter-monitor")
    public String limiterMonitor(HashMap<String, Object> map) {
        return "limiter-monitor";
    }

    @RequestMapping("degrade-configs")
    public String degradeConfigs(HashMap<String, Object> map) {
        return "degrade-configs";
    }

    @RequestMapping("degrade-config")
    public String degradeConfig(HashMap<String, Object> map) {
        return "degrade-config";
    }

}
